<?php
/* QQ:34734852
 * 业务联系：小鱼
 */
class DataBase {
	private static $ServerAddRess = 'localhost', $ServerUser = 'root', $ServerPass = '', $ServerBase = 'base', $ServerCode = 'utf8', $Pix = '', $Cache = 0;
	private $Table = '', $Where = '', $Order = '', $Limit = 0, $Sql = '', $Nums = 0, $Pao = array();
	public  $cid   = 0;
	private $Conn  = object;
	private $Ca    = false;
	private $Array = array();
	private $NewDB = '';
	public  $SDB   = '', $F = ' * ';
	public  $Pg    = 1, $zy = 1, $zt = 1, $mt = 1, $FenYe = array();
	
	public function Start( $Arr = array() ) {
		   DataBase::$ServerAddRess = $Arr['ServerAddRess'];
		   DataBase::$ServerUser    = $Arr['ServerUser'];
		   DataBase::$ServerPass    = $Arr['ServerPass'];
		   DataBase::$ServerBase    = $Arr['ServerBase'];
		   DataBase::$ServerCode    = $Arr['ServerCode'];
		   DataBase::$Pix           = $Arr['ServerPix'];
		   DataBase::$Cache         = $Arr['SelCache'];
		   unset( $Arr );
	}
	
	public function set( $val ) {
		   DataBase::$ServerBase = $val;
	}
	
	public function get() {
		  return DataBase::$ServerBase;
	}
	
	private function Null() {
		  $this->Table = $this->Where = $this->Order = $this->Sql = $this->Array ='';
		  $this->cid   = $this->Limit = $this->Nums  = 0;
		  $this->F     = ' * ';
	}
	
	public function Db( $DB = 'base' ) {
		 $this->NewDB = $DB;
		 unset( $DB );
		 return $this;
	}
	
	public function Table( $DB = 'table' ) {
		   $this->Null();
		   if ( !is_array( $DB ) ) {
		       $this->Table = '`' . DataBase::$Pix  . $DB . '`';
		   } elseif (sizeof( $DB ) <= 2 ) {
			   $Tab = array();
			   foreach( $DB as $tables ) {
				   $Tab[] = '`' .  self::$Pix . $tables . '`';
				   $this -> Pao[] = self::$Pix . $tables;
			   }
			   $this -> Table = join(', ', $Tab );
		   } else {
			   $this->Table = '`' . DataBase::$Pix  . $DB[0] . '`';
		   }
		   unset( $DB, $Tab, $tables );
		   return $this;
	}
	
	public function Field( $F = '', $Cname = array(), $ZhuHe = false ) {
          $Field = array();
		  if ( !$ZhuHe ) {
			  if ( !empty( $F ) && $F != '*' ) {
				  $Arr = preg_split('/\s?[\,\，\/\\\|\&\^\#\%\@]\s?/is', $F );
				  foreach( $Arr as $val ) {
					  $val     = trim( $val );
					  $Field[] = "`{$val}`";
				  }
				  unset( $F, $Arr, $val );
			  } else {
				  $Field[] = '*';
			  }
			  if ( is_array( $Cname ) && sizeof( $Cname ) ) {
				  foreach( $Cname as $key => $val ) {
					  $Field[] = " {$val} as `$key`";
				  }
			  }
		  } else {
			 if ( empty( $F ) || trim($F) == '*' ) {
				 $Field[] = ' `{$this->Pao[0]}`.* ';
			 } else {
				 $Exa = explode(',', $F);
				 foreach( $Exa as $fs ) {
					 $fs      = trim( $fs );
					 $Field[] = "`{$this->Pao[0]}`.`{$fs}`";
				 }
			 }
			 if ( empty($Cname) || trim( $Cname ) == '*' ) {
				 $Field[] = ' `{$this->Pao[1]}`.* ';
			 } else {
				 $Exb  = explode(',', $Cname);
				 foreach( $Exb as $ft ) {
					 $ft      = trim( $ft );
					 $Field[] = "`{$this->Pao[1]}`.`{$ft}`"; 
				 }
			 }
		  }
		  $this -> F = join(', ', $Field );
		  unset( $Arr, $Cname, $F, $Field, $fs, $ft, $key, $ZhuHe, $val, $Exa, $Exb );
		  return $this;
	}
	
	public function Cname( $as = '' ) {
		if ( empty( $as ) ) {
			return array();
		} else {
			$this -> Sql(1);
			return substr($this -> Sql, 0, 6) == 'select' ? array( $as => "({$this->Sql})" ) : array();
		}
	}
		
	public function Where( $Where = '', $arr = array() ) {
		$Where = str_replace('%', "`{$this->Pao[1]}`.", str_replace('#', "`{$this->Pao[0]}`.", $Where));
		if ( is_string( $Where ) && !empty( $Where ) ) {
		 if ( is_array( $arr ) && sizeof( $arr ) ) {
			$Where = explode('?', $Where);
			(sizeof( $arr ) < (sizeof( $Where ) - 1 )) && $arr   = array_merge( $arr, array_fill(sizeof( $arr ) + 1, sizeof( $Where ) - 1 - sizeof( $arr ), ''));
			foreach( $arr as $k => $val ) {
				!is_numeric( $val ) && $val = "'{$val}'";
				$Where[ $k ] .= $val;  
			}
			$Where = join(' ', $Where );
		 }
		 $this->Where = !empty( $Where )  ? ' Where ' . $Where . ' ' : '';
		}
		 unset( $Where, $arr, $k, $val );
		 return $this;
	}
	
	public function Order( $Order = array() ) {
		 if ( is_array( $Order ) && sizeof( $Order ) ) {
			 $DESC = array();
			 foreach( $Order as $key => $val ) {
				 $key = str_replace('%', "{$this->Pao[1]}`.`", str_replace('#', "{$this->Pao[0]}`.`", $key));
				 $DESC[] = $val ? "`{$key}` asc" : "`{$key}` desc";
			 }
			 $this -> Order = ' order by ' . join(', ', $DESC);
		 }
		 unset( $Order);
		 return $this;
	}
	
	public function How( $Num = 0 ) {
		$this->Nums = $Num;
		$this->Limit = $Num > 0 ? ' Limit ' . $Num . ' ' : 0;
		unset( $Num );
		return $this;
	}
	
	public function Arr( $Arr = array() ) {
		$this->Array = $Arr;
		unset( $Arr );
		return $this;
	}
	
	public function Page( $Num = 1, $D = 1 ) { //分页
		$this->Pg = $D or $this->Pg = 1;
		!empty( $this->Pg ) && is_numeric( $this->Pg) && $this->Pg >= 1 or $this->Pg = 1;
		$this->Executive(1);
		$this->zy =  ceil( $this->cid / $Num ) or $this -> zy = 1;
		$this->Pg <= $this->zy or $this->Pg = $this->zy;
		$this->zt =  ( $this->Pg -1 ) * $Num;
		$this -> Limit = ' Limit ' . $this -> zt . ', ' . $Num . ' ';
		$this->mt = $Num;
		return $this;
	}
	
	
	public function Select( $Num = false, $Cache  =  false ) {
		$this->Ca = $Cache;
		$Rult = $this->Executive(1);
		//echo $this -> Sql, '<br/>';
		if ( !$this->cid ){
			return false;
		} elseif ( $this->Nums == 1 ) {
			return !$Num ? $Rult -> fetch_assoc() : $Rult -> fetch_row();
		} else {
			if ( ((int)str_replace('.', '', PHP_VERSION) * 1)  >= 5500 ) { 
		        return !$Num ? $Rult -> fetch_all(MYSQLI_ASSOC) : $Rult -> fetch_all(MYSQLI_NUM);
			} else {
			  if ( !$Num ) {
				while( $Rs = $Rult -> fetch_assoc() ) {
					$Data[] = $Rs;
				}
			  } else {
				while( $Rs = $Rult -> fetch_row() ) {
					$Data[] = $Rs;
				}
			  }
				return $Data;
			}
		}
	}
	
	public function Call( $Name = 'Sub', $Arr = array(), $return = true ) { //这个方法是特有的， 用于执行Msql储存过程，调用方式是 $this -> M -> Call( 储存过程名称， 储存过程参数数组) 注意的是， 数组必须为一维数组，且要注意顺序
		$Keys = '';
		if ( is_array( $Arr ) ) {
			foreach( $Arr as $key => $val ) {
				$val = str_replace('\'', '\\\'', $val);
			    is_numeric( $val ) or $Arr[ $key ]  = '\'' .  $val . '\'';
			}
			$Keys = join(', ', $Arr );
		} 
		$this->Sql = 'call `' . $Name . '`(' . $Keys . ')';
		$Rult = $this->Executive(0);
		$this->NewDB = '';
		if ( !$this->cid ){
			return false;
		} elseif ( !$return  ) {
			return $this->cid;
		} elseif ( $this->Nums == 1 ) {
			return $Rult -> fetch_assoc();
		} else {
		  if ( ((int)str_replace('.', '', PHP_VERSION) * 1)  >= 5500 ) { 
		    return $Rult -> fetch_all(MYSQLI_ASSOC);
		  } else {
			while( $Rs = $Rult -> fetch_assoc() ) {
				$Data[] = $Rs;
			}
		    return $Data;
		  }
		}
	}
	
	public function Update( $arr = array() ) {
		if ( is_array( $arr ) && sizeof( $arr ) ) {
		  $this->Array = $arr;	
		}
		$this->Executive(3);
		$this->NewDB = '';
		return $this->cid;
	}
	
	public function Insert( $arr = array() ) {
		if ( is_array( $arr ) && sizeof( $arr ) ) {
		  $this->Array = $arr;	
		}
		$this->Executive(2);
		$this->NewDB = '';
		return $this->cid;
	}
	
	public function Delete() {
		$this->Executive(4);
		$this->NewDB = '';
		return $this->cid;
	}
	
	public function Count() {
		$this->Executive(1);
		$this->NewDB = '';
		return $this->cid;
	}
	
	public function Trun() {
		return $this->Executive(5);
	}
	
	private function Sql( $type = 1 ) {
		switch( $type ) {
			case 1:
			      $this->Sql = 'select ' . $this->F . ' from ' . $this->Table . $this->Where . $this->Order . ($this->Limit ? $this->Limit : ''); break;
		    case 0:
			       $this->Sql = $this->Sql; break;
		    case 3:
			       if ( is_array( $this->Array ) && sizeof( $this->Array ) ) {
					   $Set = array();
					   foreach( $this->Array as $key => $val ) {
						  //$val = htmlentities( $val, ENT_QUOTES );
						  if ( preg_match('/^[\+\-\*\/\%]{1}/is', $val) ) {
						   $Set[] = '`' . $key . '` = `' . $key . '` ' . $val;
						  } else {
						   is_numeric( $val ) or $val = '\'' .  $val . '\'';
						   $Set[] = '`' . $key . '` = ' . $val;
						  }
					   }
					   $this->Sql ='Update ' . $this->Table . ' Set ' . join(', ', $Set) .  $this->Where;
					   unset( $key, $Set, $type, $val );
				   } else {
					  $this -> Error('数据命令错误', false);
				   }
			     break;
		   case 2:
			       if ( is_array( $this->Array ) && sizeof( $this->Array ) ) {
					   $field = $values = array();
					   foreach( $this->Array as $key => $val ) {
						   //$val = htmlentities( $val );
						   is_numeric( $val ) or $val = '\'' .  $val . '\'';
						   $field[]  = '`' . $key . '`';
						   $values[] = $val;
					   }
					   $this->Sql = 'Insert into ' . $this->Table . ' (' . join(', ', $field) . ') values (' . join(', ', $values) . ')';
					   unset( $field, $key, $Set, $type, $val, $values );
				   } else {
					  $this -> Error('数据命令错误');
				   }
		       break;
		  case 4:
		       $this->Sql = 'Delete from ' . $this->Table . $this->Where; break;
	      case 5:
		       $this -> Sql = "truncate table {$this->Table}"; break;
		}
		 
	}
	
	private function Executive( $Type = 1, $Call = false ) {
		$this->cid = 0;
		$this->Sql( $Type );
		$this->Connect();
		$Data = $this->Conn->query($this->Sql);
		$this->NewDB = '';
		if ( $this->Conn->errno ) {
			$this->Error('数据库命令未能成功执行<br/>数据命令：' . $this->Sql . '<br/>错误标示：' . $this->Conn->errno . '<br/>错误信息：' . $this->Conn->error . BAIDUFANYI::API($this->Conn->error) );
		} else {
			if ( $Type == 1 ) {
				$this->cid   = $Data->num_rows;
				$this->FenYe = array('zongtiaoshu' => $this->cid, 'meiyetiaoshu' => $this->mt, 'zongyeshu' => $this->zy, 'dangqianyeshu' => $this->Pg);
			} elseif ( $Type ==  2 ) {
				$this->cid = $this->Conn->insert_id;
			} elseif ( $Type == 0 ) {
				if ( $Data->num_rows ) {
					$this->cid = $Data->num_rows;
				} elseif ( $this->Conn->insert_id ) {
					$this->cid = $this->Conn->insert_id;
				} else {
					$this->cid = $this->Conn->affected_rows;
				}
			} else {
				$this->cid = $this->Conn->affected_rows;
			}
			$this -> Conn -> close();
		  return $Data;
		}
	}
	
	/*
	  Execute 直接执行sq语句 &&数据表前缀通配符
	  $Sql    Sql语句
	  $Number 返回记录条数true
	  $Complex 返回多条true
	*/
	public function Execute( $Sql = '', $Complex = false, $Number = false ) {
		$Sql = str_replace('&&', self::$Pix, $Sql);
		$this -> cid = 0;
		$this->NewDB = '';
		$this -> Connect();
		$Data = $this -> Conn -> query( $Sql );
		$this -> Conn -> errno && $this->Error('数据库命令未能成功执行<br/>数据命令：' . $Sql . '<br/>错误标示：' . $this -> Conn -> errno . '<br/>错误信息：' . $this -> Conn -> error .BAIDUFANYI::API($this -> Conn -> error), false );
	    switch( true ) {
			case preg_match('/^\s?insert\s+into\s?/is', $Sql):
			     return $this -> Conn -> insert_id;
				 break;
			case preg_match('/^\s?(update|delete)\s+/is', $Sql):
			     return $this -> Conn -> affected_rows;
				 break;
		    case preg_match('/^\s?select\s+/is', $Sql):
			     if ( $Number ) {
					 return $Data -> num_rows;
				 } elseif ( !$Data -> num_rows )  {
					 return false;
				 } else {
					 if ( !$Complex ) {
						 return $Data -> fetch_assoc();
					 } else {
						 return $this -> TreatmentResult( $Data );
					 }
				 }
			     break;
			default: return false;
		}
	}
	
	private function TreatmentResult( $Data = object ) {
		if ( ((int)str_replace('.', '', PHP_VERSION) * 1)  >= 5500 ) { 
		    return $Data -> fetch_All( MYSQLI_ASSOC );
		} else {
			while( $Rult = $Data -> fetch_assoc() ){
				$Rs[] =  $Rult;
			}
			return $Rs;
		}
	}
	
	
	private function Connect() {
		try{
		 if ( empty($this->SDB) ) {
		     $this->Conn = @new mysqli( DataBase::$ServerAddRess, DataBase::$ServerUser, DataBase::$ServerPass, empty( $this->NewDB ) ? DataBase::$ServerBase : $this->NewDB);
		 } else {
			 $this->Conn = @new mysqli( DataBase::$ServerAddRess, DataBase::$ServerUser, DataBase::$ServerPass,  $this->SDB );
		 }
		  !mysqli_connect_errno() or $this->Error('数据库未能成功连接<br/>错误标示：' . mysqli_connect_errno() . '<br/>错误信息：' . mysqli_connect_error() . BAIDUFANYI::API(mysqli_connect_error()), false );
		  $this->Conn->query('set names ' . DataBase::$ServerCode);
		}catch(Exception $e) {
			
		}
	}
	
	
	private function Error( $Msg = '', $Exit = true ) {
	      file_put_contents(ROOT . APP . '/Log/database-error.log', str_replace('<br/>', '  ', $Msg) . "\r\r\n", FILE_APPEND);
		  include_once LIB . 'Template/Error_Write.tpl';
		  unset( $Msg );
		  if( !$Exit ) {
			 unset( $Exit, $Msg );
			 die; 
		  }
		  unset( $Exit, $Msg );
	}
	
}
